﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SmartSpace.Core
{
    public partial class CoreService : ICoreService
    {
        public CoreService()
        {
        }

        public User GetUser(string account)
        {
            using (CoreDbContext context = new CoreDbContext())
            {
                return context.Set<User>()
                    .Where(p => p.Account == account)
                    .FirstOrDefault();
            }
        }

        public User GetUser(Guid id)
        {
            using (CoreDbContext context = new CoreDbContext())
            {
                return context.Set<User>()
                    .Where(p => p.Id == id)
                    .FirstOrDefault();
            }
        }

        public List<User> GetUsers(List<Guid> idList)
        {
            using (CoreDbContext context = new CoreDbContext())
            {
                return (from order in context.Set<User>()
                              where (idList.Contains(order.Id))
                              select order).ToList();
            }
        }

        public PagedList<User> GetUsers(int start, int limit)
        {
            using (CoreDbContext context = new CoreDbContext())
            {
                List<User> list = context.Set<User>()
                    .OrderByDescending(p => p.Account)
                    .Skip(start)
                    .Take(limit)
                    .ToList();
                PagedList<User> pagedList = new PagedList<User>();
                foreach (User item in list)
                {
                    pagedList.Add(item);
                }
                pagedList.Start = start;
                pagedList.Limit = limit;
                pagedList.Total = context.Set<User>().Count();

                return pagedList;
            }
        }
        
        public PagedList<User> FindUsers(string filter, int start, int limit)
        {
            using (CoreDbContext context = new CoreDbContext())
            {
                List<User> list = context.Set<User>()
                    .Where(p=>p.Account.Contains(filter) || p.Name.Contains(filter))
                    .OrderByDescending(p => p.Account)
                    .Skip(start)
                    .Take(limit)
                    .ToList();
                PagedList<User> pagedList = new PagedList<User>();
                foreach (User item in list)
                {
                    pagedList.Add(item);
                }
                pagedList.Start = start;
                pagedList.Limit = limit;
                pagedList.Total = context.Set<User>().Where(p => p.Account.Contains(filter) || p.Name.Contains(filter)).Count();

                return pagedList;
            }
        }


        public bool SaveUser(User user)
        {
            using (CoreDbContext context = new CoreDbContext())
            {
                if (context.Set<User>()
                    .Where(p => p.Id == user.Id)
                    .Select(p=>p.Id)
                    .FirstOrDefault() == default(Guid))
                {
                    context.Set<User>().Add(user);
                }
                else
                {
                    context.Entry(user).State = System.Data.Entity.EntityState.Modified;
                }

                context.SaveChanges();
                return true;
            }
        }

        public bool DeleteUser(User user)
        {
            using (CoreDbContext context = new CoreDbContext())
            {
                if (context.Set<User>()
                    .Where(p => p.Id == user.Id)
                    .Select(p => new { p.Id })
                    .FirstOrDefault() != null)
                {
                    context.Entry(user).State = System.Data.Entity.EntityState.Deleted;
                }
                context.SaveChanges();
                return true;
            }
        }

        public bool DeleteUser(Guid userId)
        {
            using (CoreDbContext context = new CoreDbContext())
            {
                User user = context.Set<User>()
                    .Where(p => p.Id == userId)
                    .FirstOrDefault();

                if (user != null)
                {
                    context.Entry(user).State = System.Data.Entity.EntityState.Deleted;
                    if (context.SaveChanges() > 0)
                    {
                        return true;
                    }
                }
                return false;
            }
        }

        //public bool AssignUser(Role role, User user, User assigner)
        //{
        //    using (CoreDbContext context = new CoreDbContext())
        //    {
        //        RelationRoleToUser relation = new RelationRoleToUser();
        //        relation.Id = Guid.NewGuid();
        //        relation.User = null;
        //        relation.UserId = user.Id;
        //        relation.Role = null;
        //        relation.RoleId = role.Id;
        //        relation.Assigner = null;
        //        relation.AssignerId = assigner.Id;
        //        relation.AssignedTime = DateTime.Now;

        //        if (context.Set<RelationRoleToUser>()
        //            .Where(p => p.User.Id == user.Id && p.Role.Id == role.Id)
        //            .FirstOrDefault() == null)
        //        {
        //            context.Set<RelationRoleToUser>().Add(relation);
        //            context.SaveChanges();
        //            return true;
        //        }

        //        return false;
        //    }
        //}
        
        //public bool RemoveUser(Role role, User user)
        //{
        //    using (CoreDbContext context = new CoreDbContext())
        //    {
        //        RelationRoleToUser relation = context.Set<RelationRoleToUser>()
        //            .Where(p => p.Role.Id == role.Id && p.User.Id == user.Id)
        //            .FirstOrDefault();

        //        if (relation != null)
        //        {
        //            context.Set<RelationRoleToUser>().Remove(relation);
        //            context.SaveChanges();
        //            return true;
        //        }

        //        return false;
        //    }
        //}

        //public List<Role> GetAssignedRoles(User user)
        //{
        //    using (CoreDbContext context = new CoreDbContext())
        //    {
        //        List<Role> roles = context.Set<Role>().Select(p => p)
        //            .Join(
        //                context.Set<RelationRoleToUser>().Where(r => r.UserId == user.Id),
        //                p => p.Id,
        //                v => v.RoleId,
        //                (p, v) => p).ToList();
        //        return roles;
        //    }
        //}

        //public List<User> GetContainsUsers(Role role)
        //{
        //    using (CoreDbContext context = new CoreDbContext())
        //    {
        //        return context.Set<User>().Select(p => p)
        //            .Join(
        //                context.Set<RelationRoleToUser>().Where(r => r.Role.Id == role.Id),
        //                p => p.Id,
        //                v => v.User.Id,
        //                (p, v) => p).ToList();
        //    }
        //}

        //public List<User> GetContainsUsers(Guid roleId)
        //{
        //    using (CoreDbContext context = new CoreDbContext())
        //    {
        //        return context.Set<User>().Select(p => p)
        //            .Join(
        //                context.Set<RelationRoleToUser>().Where(r => r.Role.Id == roleId),
        //                p => p.Id,
        //                v => v.User.Id,
        //                (p, v) => p).ToList();
        //    }
        //}

        public bool SaveModule(Module module)
        {
            using (CoreDbContext context = new CoreDbContext())
            {
                if (context.Set<Module>()
                    .Where(p => p.Id == module.Id)
                    .Select(p => new { p.Id })
                    .FirstOrDefault() == null)
                {
                    context.Set<Module>().Add(module);
                }
                else
                {
                    context.Entry(module).State = System.Data.Entity.EntityState.Modified;

                    List<ModuleView> existViews = context.Set<ModuleView>().Where(p => p.ModuleId == module.Id).ToList();
                    foreach (var existView in existViews)
                    {
                        bool isExist = false;
                        foreach (var view in module.Views)
                        {
                            if (existView.Id == view.Id)
                            {
                                existView.Caption = view.Caption;
                                existView.Code = view.Code;
                                isExist = true;
                                break;
                            }
                        }

                        if (!isExist)
                        {
                            context.Entry(existView).State = System.Data.Entity.EntityState.Deleted;
                        }
                        else
                        {
                            context.Entry(existView).State = System.Data.Entity.EntityState.Modified;
                        }
                    }

                    foreach (var view in module.Views)
                    {
                        bool isExist = false;
                        foreach (var existView in existViews)
                        {
                            if (existView.Id == view.Id)
                            {
                                isExist = true;
                                break;
                            }
                        }

                        if (!isExist)
                        {
                            context.Set<ModuleView>().Add(view);
                        }
                    }
                }

                context.SaveChanges();
                return true;
            }
        }

        public Module GetModule(Guid moduleId)
        {
            using (CoreDbContext context = new CoreDbContext())
            {
                return context.Set<Module>().Where(p => p.Id == moduleId).SingleOrDefault();
            }
        }

        public PagedList<Module> GetModules(int start, int limit)
        {
            using (CoreDbContext context = new CoreDbContext())
            {
                List<Module> list = context.Set<Module>()
                    .Include("Views")
                    .OrderByDescending(p => p.Code)
                    .Skip(start)
                    .Take(limit)
                    .ToList();
                PagedList<Module> pagedList = new PagedList<Module>();
                foreach (Module item in list)
                {
                    pagedList.Add(item);
                }
                pagedList.Start = start;
                pagedList.Limit = limit;
                pagedList.Total = context.Set<Module>().Count();

                return pagedList;
            }
        }

        public PagedList<Module> GetModules(string type, int start, int limit)
        {
            using (CoreDbContext context = new CoreDbContext())
            {
                List<Module> list = context.Set<Module>()
                    .Include("Views")
                    .Where(p=>p.Type == type)
                    .OrderByDescending(p => p.Code)
                    .Skip(start)
                    .Take(limit)
                    .ToList();
                PagedList<Module> pagedList = new PagedList<Module>();
                foreach (Module item in list)
                {
                    pagedList.Add(item);
                }
                pagedList.Start = start;
                pagedList.Limit = limit;
                pagedList.Total = context.Set<Module>().Where(p => p.Type == type).Count();

                return pagedList;
            }
        }

        public ModuleView GetView(Guid viewId)
        {
            using (CoreDbContext context = new CoreDbContext())
            {
                return context.Set<ModuleView>()
                    .Include("Module")
                    .Where(p => p.Id == viewId).FirstOrDefault();
            }
        }

        public Navigation GetNavigation(Guid id)
        {
            using (CoreDbContext context = new CoreDbContext())
            {
                return context.Set<Navigation>().Where(p => p.Id == id).SingleOrDefault();
            }
        }

        public bool SetDefaultNavigation(Guid id)
        {
            using (CoreDbContext context = new CoreDbContext())
            {
                //Navigation navigation = context.Set<Navigation>().Where(p => p.Id == id).SingleOrDefault();
                //if (navigation == null)
                //{
                //    return false;
                //}

                //if (!navigation.IsDefault)
                //{
                //    navigation.IsDefault = true;
                //    // 清除现在的默认导航
                //    Navigation defaultNavigation = context.Set<Navigation>()
                //        .Where(p => p.ApplicationId == navigation.ApplicationId && p.IsDefault == true)
                //        .SingleOrDefault();

                //    if (defaultNavigation != null)
                //    {
                //        defaultNavigation.IsDefault = false;
                //        context.Entry(defaultNavigation).State = System.Data.Entity.EntityState.Modified;
                //    }
                //    context.Entry(navigation).State = System.Data.Entity.EntityState.Modified;

                //    if (context.SaveChanges() > 0)
                //    {
                //        return true;
                //    }
                //}

                return false;
            }
        }

        #region
        public bool AddShortcut(Guid navigationId, string caption)
        {
            using (CoreDbContext context = new CoreDbContext())
            {
                Navigation navigation = context.Set<Navigation>()
                    .Where(p=>p.Id == navigationId)
                    .SingleOrDefault();

                if (navigation != null && context.Set<Shortcut>()
                    .Where(p => p.NavigationId == navigationId)
                    .Select(p => p.Id)
                    .FirstOrDefault() == Guid.Empty)
                {
                    Shortcut shortcut = new Shortcut();
                    shortcut.Id = Guid.NewGuid();
                    shortcut.NavigationId = navigationId;
                    if (string.IsNullOrEmpty(caption))
                    {
                        shortcut.Caption = navigation.Caption;
                    }
                    else
                    {
                        shortcut.Caption = caption;
                    }

                    context.Set<Shortcut>().Add(shortcut);

                    if (context.SaveChanges() > 0)
                    {
                        return true;
                    }
                }
                return false;
            }
        }

        public bool DeleteShortcut(Guid navigationId)
        {
            using (CoreDbContext context = new CoreDbContext())
            {
                Shortcut shortcut = context.Set<Shortcut>()
                    .Where(p => p.NavigationId == navigationId)
                    .SingleOrDefault();

                if (shortcut != null)
                {
                    context.Entry(shortcut).State = System.Data.Entity.EntityState.Deleted;

                    if (context.SaveChanges() > 0)
                    {
                        return true;
                    }
                }
                return false;
            }
        }

        public List<Shortcut> GetShortcuts(Guid applicationId)
        {
            using (CoreDbContext context = new CoreDbContext())
            {
                List<Shortcut> shortcuts = context.Set<Shortcut>()
                    .Join(context.Set<Navigation>().Where(p => p.SiteId == applicationId),
                        shortcut => shortcut.NavigationId,
                        navigation => navigation.Id,
                        (shortcut, navigation) => shortcut)
                    .ToList();

                return shortcuts;
            }
        }
        #endregion

        public Role GetRole(Guid roleId)
        {
            using (CoreDbContext context = new CoreDbContext())
            {
                return context.Set<Role>().Where(p => p.Id == roleId).FirstOrDefault();
            }
        }

        #region module

        public List<Site> GetPersonalApplications(string account)
        {
            using (CoreDbContext context = new CoreDbContext())
            {
                string sql = @"select a.* from __application as a
 join __navigation as n on n.applicationid = a.id
 join __roleNavigation as rn on rn.navigationid = n.id
 join __relationRoleToUser as ru on ru.roleid = rn.roleid
 join __user as u on u.id = ru.userid
 where u.account={0}";
                return context.Database.SqlQuery<Site>(sql, account).ToList();
            }
        }

        public Site GetPersonalDefaultApplication(string account)
        {
            using (CoreDbContext context = new CoreDbContext())
            {
                string sqlDefault = @"select top 1 a.* from __application as a
 join __navigation as n on n.applicationid = a.id
 join __roleNavigation as rn on rn.navigationid = n.id
 join core_userrole as ur on ur.roleid = rn.roleid
 join __user as u on u.id = ur.userid
 where u.account={0} and a.isDefault={1}";
                string sqlTop1 = @"select top 1 a.* from __application as a
 join __navigation as n on n.applicationid = a.id
 join __roleNavigation as rn on rn.navigationid = n.id
 join core_userrole as ur on ur.roleid = ur.roleid
 join __user as u on u.id = ur.userid
 where u.account={0}";
                Site application = context.Database.SqlQuery<Site>(sqlDefault, account, true).SingleOrDefault();
                if (application == null)
                {
                    application = context.Database.SqlQuery<Site>(sqlTop1, account).SingleOrDefault();
                }
                return application;
            }
        }

        public List<Site> GetPersonalApplications(string type, string account)
        {
            using (CoreDbContext context = new CoreDbContext())
            {
                string sql = @"select distinct a.* from __application as a
 join __navigation as n on n.applicationid = a.id
 join __roleNavigation as rn on rn.navigationid = n.id
 join __relationRoleToUser as ru on ru.roleid = rn.roleid
 join __user as u on u.id = ru.userid
 where u.account={0} and a.type={1}";
                return context.Database.SqlQuery<Site>(sql, account, type).ToList();
            }
        }

        public Site GetPersonalDefaultApplication(string type, string account)
        {
            using (CoreDbContext context = new CoreDbContext())
            {
                string sqlDefault = @"select top 1 a.* from __application as a
 join __navigation as n on n.applicationid = a.id
 join __roleNavigation as rn on rn.navigationid = n.id
 join __relationRoleToUser as ru on ru.roleid = rn.roleid
 join __user as u on u.id = ru.userid
 where u.account={0} and a.isDefault={1} and a.type={2}";
                string sqlTop1 = @"select top 1 a.* from __application as a
 join __navigation as n on n.applicationid = a.id
 join __roleNavigation as rn on rn.navigationid = n.id
 join __relationRoleToUser as ru on ru.roleid = rn.roleid
 join __user as u on u.id = ru.userid
 where u.account={0} and a.type={1}";
                Site application = context.Database.SqlQuery<Site>(sqlDefault, account, true, type).SingleOrDefault();
                if (application == null)
                {
                    application = context.Database.SqlQuery<Site>(sqlTop1, account, type).SingleOrDefault();
                }
                return application;
            }
        }

        public bool AssignModuleToSite(Guid siteId, Guid moduleId)
        {
            using (CoreDbContext context = new CoreDbContext())
            {
                if (context.Set<SiteModuleRelation>()
                    .Where(p => p.SiteId == siteId && p.ModuleId == moduleId)
                    .Select(p => new { p.Id })
                    .FirstOrDefault() == null)
                {
                    SiteModuleRelation model = new SiteModuleRelation();
                    model.Id = Guid.NewGuid();
                    model.SiteId = siteId;
                    model.ModuleId = moduleId;
                    context.Set<SiteModuleRelation>().Add(model);

                    if (context.SaveChanges() > 0)
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
                else
                {
                    return false;
                }
            }
        }

        public bool RemoveModuleFromSite(Guid siteId, Guid moduleId)
        {
            using (CoreDbContext context = new CoreDbContext())
            {
                SiteModuleRelation model = context.Set<SiteModuleRelation>()
                    .Where(p => p.SiteId == siteId && p.ModuleId == moduleId)
                    .FirstOrDefault();

                if (model != null)
                {
                    context.Entry(model).State = System.Data.Entity.EntityState.Deleted;

                    if (context.SaveChanges() > 0)
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
                else
                {
                    return false;
                }
            }
        }

        public List<Module> GetModules(Guid siteId)
        {
            using (CoreDbContext context = new CoreDbContext())
            {
                List<Module> list = new List<Module>();
                List<Module> modules = context.Set<Module>()
                    .Include("Views")
                    .ToList();
                List<SiteModuleRelation> relations = context.Set<SiteModuleRelation>()
                    .Where(p=>p.SiteId == siteId).ToList();

                foreach (var module in modules)
                {
                    foreach (var am in relations)
                    {
                        if (module.Id == am.ModuleId)
                        {
                            list.Add(module);
                            break;
                        }
                    }
                }

                return list;
            }
        }
        #endregion

        #region Image
        public bool SaveImage(Image image)
        {
            using (CoreDbContext context = new CoreDbContext())
            {
                if (context.Set<Image>()
                    .Where(p => p.Id == image.Id)
                    .Select(p => new { p.Id })
                    .FirstOrDefault() == null)
                {
                    context.Set<Image>().Add(image);
                }
                else
                {
                    context.Set<Image>().Attach(image);
                }

                if (context.SaveChanges() > 0)
                {
                    return true;
                }
                return false;
            }
        }

        public bool DeleteImage(Guid imageId)
        {
            using (CoreDbContext context = new CoreDbContext())
            {
                Image image = context.Set<Image>()
                    .Where(p => p.Id == imageId).FirstOrDefault();
                if (image != null)
                {
                    context.Entry(image).State = System.Data.Entity.EntityState.Deleted;

                    if (context.SaveChanges() > 0)
                    {
                        return true;
                    }
                }
                return false;
            }
        }

        public Image GetImage(Guid imageId)
        {
            using (CoreDbContext context = new CoreDbContext())
            {
                return context.Set<Image>().Where(p => p.Id == imageId).SingleOrDefault();
            }
        }

        public List<Image> GetImages()
        {
            using (CoreDbContext context = new CoreDbContext())
            {
                return context.Set<Image>()
                    .Select(p => new Image { Id = p.Id, Extension = p.Extension, SortIndex = p.SortIndex })
                    .ToList();
            }
        }
        #endregion
    }
}
